#ifndef FCSP_H
#define FCSP_H

#include <algorithm>
#include <list>
#include <stdlib.h>
#include <time.h>
#include <vector>

#include "variable.h"
#include "binary_constraint.h"

namespace fcsp {
class FCSP {
 public:
  // static constants
  static const double kLowerPref = 0.0;
  static const double kUpperPref = 1.0;

  // constructors
  FCSP();

  // destructors
  virtual ~FCSP();
  
  // accessors
  std::list<BinaryConstraint> &binary_constraints() {
    return binary_constraints_;
  }
  std::list<Variable> &variables() { return variables_; }
  
  // methods
  Variable &AddVariable(); // add a variable to csp
  Variable &AddVariable(std::set<int> &values); // add a variable to csp
  Variable &AddVariable(std::map<int, double> &preferences); // add a variable to csp
  std::pair<Variable&, bool> GetVariable(Variable &x); // get a variable from csp
  void RemoveVariable(Variable &); // remove a variable fom csp
  BinaryConstraint &AddConstraint(Variable &x, Variable &y); // add constraint to csp
  BinaryConstraint &AddConstraint(Variable &x, Variable &y,
    std::map< int, std::map<int, double> > preferences); // add constraint to csp
  std::pair<BinaryConstraint&, bool> GetConstraint(Variable &x, Variable &y); // get a constraint
  void RemoveConstraint(Variable &x, Variable &y); // remove a constraint from csp
  // get a preference of a constraint assignment
  double GetConstraintPref(Variable &x, Variable &y, int value_x, int value_y);
  // set a preference of a constraint assignment
  void SetConstraintPref(Variable &x, Variable &y, int value_x, int value_y, double pref);
  void SetVariablePref(Variable &x, int value_x, double pref); // set a preference of variable value
  // generates a random instance of a csp
  void GenCSP(int var_num, int var_card, double density, double tightness);

  // static methods
  // check if a pref is the lower/upper preference (0.0/1.0)
  static bool IsLowerPref(double pref) { return pref <= kLowerPref + 1.0e-06; }
  static bool IsUpperPref(double pref) { return pref >= kUpperPref - 1.0e-06; }

 private:
  std::list<BinaryConstraint> binary_constraints_; // list of binary constraints
  std::list<Variable> variables_; // list of variable

  // generates a list of preference for a variable
  void GenVariablePrefs(int, double, std::map<int, double> &preferences);
  // generates a list of preference for a constraint
  void GenConstraintPrefs(const Variable &, const Variable &, double,
    std::map< int, std::map<int, double> > &preferences);
}; // class FCSP
} // namespace fcsp
#endif	// FCSP_H
